21  多维数据可视化 股票相关性分析

21.1 引言相关性的金融意义

在现代投资组合理论中,资产间的相关性是核心概念。理解相关性对于构建有效投资组合、管理风险和发现套利机会至关重要。

理论背景:相关性的数学定义

皮尔逊相关系数(Pearson Correlation Coefficient)衡量两个变量线性相关的强度和方向:

\[ \rho_{X,Y} = \frac{\text{Cov}(X,Y)}{\sigma_X \sigma_Y} = \frac{E[(X-\mu_X)(Y-\mu_Y)]}{\sigma_X \sigma_Y} \]

其中: - \(\text{Cov}(X,Y)\): 协方差 - \(\sigma_X, \sigma_Y\): 标准差 - 取值范围: \([-1, 1]\)

金融应用中的相关性:

  1. 分散化(Diversification):
    • 投资组合方差: \(\sigma_p^2 = \sum_i \sum_j w_i w_j \sigma_i \sigma_j \rho_{ij}\)
    • 相关性越低,组合风险越小
    • 马科维茨理论的核心
  2. 系统性风险:
    • 高相关性意味着暴露于共同因子
    • 市场崩盘时可能同跌
  3. 配对交易(Pairs Trading):
    • 高相关性股票可能存在价差套利机会
    • 统计套利的基础
  4. 因子模型:
    • 相关性聚类识别行业因子
    • 风格因子暴露分析

补充说明:相关性的局限性

相关系数只能衡量线性关系: - 无法捕捉非线性关系 - 对异常值敏感 - 不能推出因果关系

例如: 如果 \(Y = X^2\),且 \(X\) 对称分布,则 \(\rho_{X,Y} = 0\),但两者有强关系。

21.2 数据获取与预处理

21.2.1 获取股票价格数据

列表 21.1
# 注:该代码块存在缩进错误且使用tushare API(非用户token),渲染时无法执行
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import tushare as ts  # 导入tushare模块
import pandas as pd  # 导入Pandas数据分析库
import seaborn as sns  # 导入Seaborn可视化库
import matplotlib.pyplot as plt  # 导入Matplotlib绑图库
plt.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文

ts.set_token("1b80258a92e8a547628c8e8477d0c4c590d485d17dfa98eea5a46db7")  # 设置Tushare API访问令牌
pro=ts.pro_api()  # 初始化Tushare Pro API接口
# 获取股票代码和名称的对应关系
stock_list = {'600030.SH': '中信证券', '601318.SH': '中国平安', '600036.SH': '招商银行', '600519.SH': '贵州茅台','601668.SH':'中国建筑'}
# 获取数据
data = {}
for stock_code, stock_name in stock_list.items():  # 循环遍历
        df = pro.daily(ts_code=stock_code, start_date='20230101', end_date='20230301')  # 通过API获取df的行情数据
    data[stock_name] = df['close'].values.tolist()  # 创建列表data[stock_name]
# 转换为DataFrame
df=pd.DataFrame.from_dict(data)
# 绘制热力图
sns.heatmap(df.corr(), annot=True, cmap='coolwarm')
plt.title('股价热力图')  # 设置图表标题
plt.savefig("1.png")  # 保存图形至文件

代码深度解析:

  1. 数据来源:
    • tushare: A股免费数据源
    • 需要注册获取token
    • API限制:每分钟调用次数有限
  2. 价格模拟:
    • 几何布朗运动: \(dS_t = \mu S_t dt + \sigma S_t dW_t\)
    • 离散化: \(S_{t+1} = S_t e^{(\mu - 0.5\sigma^2)\Delta t + \sigma \epsilon \sqrt{\Delta t}}\)
    • 保持价格正性
  3. 行业因子:
    • 同行业股票受共同因子影响
    • 模拟相关性通过添加共同噪声

21.2.2 收益率计算

列表 21.2
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 计算股票收益率
# =============================================================================
# 本代码块演示如何从价格数据计算收益率。在金融分析中,我们通常使用收益率
# 而非原始价格,因为收益率具有更好的统计特性(平稳性、可加性等)。这里我们
# 同时计算简单收益率和对数收益率,并对比它们的差异。

# ==================== 计算简单收益率 ====================
# pct_change()计算百分比变化:(当前值 - 上期值) / 上期值
# 简单收益率公式: R_t = (P_t - P_{t-1}) / P_{t-1}
simple_returns = df_prices.pct_change().dropna()  # 计算简单收益率并删除第一行NaN

# ==================== 计算对数收益率 ====================
# 对数收益率公式: r_t = ln(P_t / P_{t-1}) = ln(P_t) - ln(P_{t-1})
# 对数收益率具有可加性,多期收益率可以相加
log_returns = np.log(df_prices / df_prices.shift(1)).dropna()  # 计算对数收益率并删除NaN

# ==================== 输出收益率预览 ====================
print('简单收益率(前5行):')  # 打印标题
print(simple_returns.head())  # 打印前5行简单收益率
print(f'\n对数收益率(前5行):')  # 打印标题
print(log_returns.head())  # 打印前5行对数收益率

# ==================== 收益率统计对比 ====================
print(f'\n简单收益率统计:')  # 打印标题
print(simple_returns.describe().round(4))  # 打印简单收益率的描述统计,保留4位小数

print(f'\n对数收益率统计:')  # 打印标题
print(log_returns.describe().round(4))  # 打印对数收益率的描述统计,保留4位小数

补充说明:简单收益率 vs 对数收益率

特性 简单收益率 对数收益率
公式 \(R_t = (P_t - P_{t-1}) / P_{t-1}\) \(r_t = \ln(P_t / P_{t-1})\)
可加性 多期收益率不可直接相加 可相加: \(r_{1→3} = r_1 + r_2 + r_3\)
对称性 不对称: +10%和-10%不对等 对称
分布 偏态 更接近正态分布
金融应用 报告收益 计算波动率、建模

相关性分析建议: 使用对数收益率,因为: 1. 更接近正态分布 2. 时间可加性 3. 适合连续复利假设

21.3 相关性矩阵计算与解读

21.3.1 相关系数计算

列表 21.3
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 计算股票收益率相关性矩阵
# =============================================================================
# 本代码块演示如何计算多只股票收益率之间的相关系数矩阵。相关系数矩阵是
# 多变量统计分析的基础,用于量化变量之间的线性关系强度。在金融应用中,
# 相关性矩阵是投资组合优化、风险管理和因子模型的核心输入。

# ==================== 使用对数收益率计算相关性 ====================
# corr()方法计算DataFrame中所有列两两之间的相关系数
# 默认使用皮尔逊相关系数(method='pearson')
# 皮尔逊相关系数衡量两个变量的线性相关程度,取值范围[-1, 1]
corr_matrix = log_returns.corr()  # 计算对数收益率的相关系数矩阵

# ==================== 输出相关性矩阵 ====================
print('相关性矩阵:')  # 打印标题
print(corr_matrix.round(3))  # 打印相关系数矩阵,保留3位小数
print(f'\n矩阵形状: {corr_matrix.shape}')  # 打印矩阵形状(行数,列数)

# ==================== 验证对称性 ====================
# 相关系数矩阵理论上应该是对称矩阵(即矩阵等于其转置)
# 对角线元素应该全为1(变量与自身的相关系数)
print(f'\n矩阵对称性检验:')  # 打印标题
print(f'是否对称: {np.allclose(corr_matrix, corr_matrix.T)}')  # 检验矩阵是否对称
print(f'对角线元素(应全为1): {np.diag(corr_matrix)}')  # 打印对角线元素

代码深度解析:

  1. corr()方法参数:
    • method='pearson': 皮尔逊相关(默认)
    • method='spearman': 斯皮尔曼秩相关(对异常值稳健)
    • method='kendall': 肯德尔τ相关
  2. 矩阵性质:
    • 对称性: \(\rho_{ij} = \rho_{ji}\)
    • 对角线为1: \(\rho_{ii} = 1\)
    • 正定性: 协方差矩阵半正定,相关矩阵正定(假设无完全多重共线性)
  3. 样本量要求:
    • 至少需要30个观测点
    • 样本量越大,估计越准确
    • 本例:60个交易日,勉强足够

21.3.2 相关性解读标准

列表 21.4
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 相关系数的统计显著性检验
# =============================================================================
# 本代码块演示如何对相关系数进行统计显著性检验,并按照相关性强度进行
# 分类。统计显著性检验帮助我们判断观察到的相关性是否真实存在,还是
# 仅仅由随机波动造成的。显著性水平通常设为0.05、0.01等。

# ==================== 导入统计检验库 ====================
from scipy.stats import pearsonr  # 导入皮尔逊相关系数检验函数

# ==================== 提取上三角矩阵(避免重复) ====================
# 相关系数矩阵是对称的,我们只需要上三角元素即可
n = len(corr_matrix)  # 获取矩阵维度(股票数量)
pairs = []  # 创建空列表,存储股票对及其相关系数
for i in range(n):  # 遍历行
    for j in range(i+1, n):  # 遍历列(只取上三角,j > i)
        stock1 = corr_matrix.index[i]  # 获取第i只股票名称
        stock2 = corr_matrix.columns[j]  # 获取第j只股票名称
        corr = corr_matrix.iloc[i, j]  # 获取这对股票的相关系数

        # ==================== 计算p值 ====================
        # pearsonr()返回相关系数和p值
        # p值:假设H0(相关系数=0)成立时,观察到当前或更极端统计量的概率
        # p值越小,拒绝原假设的证据越强
        _, p_value = pearsonr(log_returns[stock1], log_returns[stock2])

        # ==================== 存储结果 ====================
        pairs.append({
            '股票1': stock1,  # 第一只股票名称
            '股票2': stock2,  # 第二只股票名称
            '相关系数': corr,  # 相关系数
            'P值': p_value,  # 显著性检验的p值
            # 根据p值标注显著性:***极显著,**显著,*边缘显著,ns不显著
            '显著性': '***' if p_value < 0.01 else '**' if p_value < 0.05 else '*' if p_value < 0.1 else 'ns'
        })

# ==================== 转换为DataFrame并排序 ====================
df_pairs = pd.DataFrame(pairs).sort_values('相关系数', ascending=False)  # 按相关系数降序排序

# ==================== 输出结果 ====================
print('股票相关性分析(按相关系数排序):')  # 打印标题
print(df_pairs.to_string(index=False))  # 打印所有股票对的分析结果

# ==================== 相关性强度分类 ====================
print(f'\n相关性强度分布:')  # 打印标题
# 统计各强度区间的股票对数量
strong_pos = (df_pairs['相关系数'] >= 0.7).sum()  # 强正相关(≥0.7)的对数
moderate_pos = ((df_pairs['相关系数'] >= 0.4) & (df_pairs['相关系数'] < 0.7)).sum()  # 中度正相关(0.4-0.7)
weak_pos = ((df_pairs['相关系数'] >= 0.1) & (df_pairs['相关系数'] < 0.4)).sum()  # 弱正相关(0.1-0.4)
none = ((df_pairs['相关系数'] > -0.1) & (df_pairs['相关系数'] < 0.1)).sum()  # 无明显相关(-0.1-0.1)
weak_neg = ((df_pairs['相关系数'] > -0.4) & (df_pairs['相关系数'] <= -0.1)).sum()  # 弱负相关(-0.4--0.1)
moderate_neg = ((df_pairs['相关系数'] > -0.7) & (df_pairs['相关系数'] <= -0.4)).sum()  # 中度负相关(-0.7--0.4)
strong_neg = (df_pairs['相关系数'] <= -0.7).sum()  # 强负相关(≤-0.7)

# ==================== 输出分类统计 ====================
print(f'强正相关(≥0.7): {strong_pos}对')  # 打印强正相关对数
print(f'中度正相关(0.4-0.7): {moderate_pos}对')  # 打印中度正相关对数
print(f'弱正相关(0.1-0.4): {weak_pos}对')  # 打印弱正相关对数
print(f'无明显相关(-0.1-0.1): {none}对')  # 打印无明显相关对数
print(f'弱负相关(-0.4--0.1): {weak_neg}对')  # 打印弱负相关对数
print(f'中度负相关(-0.7--0.4): {moderate_neg}对')  # 打印中度负相关对数
print(f'强负相关(≤-0.7): {strong_neg}对')  # 打印强负相关对数

补充说明:相关性的统计显著性

相关系数的显著性检验: - 原假设 H0: \(\rho = 0\)(无相关) - 检验统计量: \(t = \frac{r\sqrt{n-2}}{\sqrt{1-r^2}}\) - P值: 观察到当前统计量的概率(假设H0成立)

显著性水平: - ***: p < 0.01 (极显著) - **: p < 0.05 (显著) - *: p < 0.10 (边缘显著) - ns: p ≥ 0.10 (不显著)

注意: 即使统计显著,经济意义上的相关性可能仍然很弱。

21.4 相关性热力图可视化

21.4.1 基础热力图

列表 21.5
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 绘制股票收益率相关性热力图
# =============================================================================
# 本代码块演示如何使用seaborn库绘制相关性热力图。热力图是可视化相关系数
# 矩阵最直观的方式,通过颜色深浅表示相关性强弱,可以快速识别股票之间的
# 关系模式。这对于投资组合构建和风险分析非常重要。

# ==================== 导入可视化库 ====================
import seaborn as sns  # 导入seaborn库,用于绘制统计图形

# ==================== 创建图形 ====================
plt.figure(figsize=(10, 8))  # 创建图形,设置尺寸为10英寸×8英寸

# ==================== 绘制热力图 ====================
sns.heatmap(
    corr_matrix,  # 输入相关系数矩阵
    annot=True,  # 在每个格子中显示数值注释
    cmap='RdYlGn',  # 设置颜色方案为红-黄-绿渐变
    center=0,  # 设置颜色中心值为0,使0相关为白色/黄色
    square=True,  # 设置格子为正方形(而不是矩形)
    linewidths=0.5,  # 设置格子之间的边框线宽为0.5
    fmt='.3f',  # 设置数值格式为保留3位小数
    cbar_kws={'label': '皮尔逊相关系数'},  # 设置颜色条标签
    vmin=-1, vmax=1  # 设置颜色映射范围为[-1, 1],这是相关系数的理论范围
)

# ==================== 设置图形属性 ====================
plt.title('股票收益率相关性热力图\n(2023年模拟数据)', fontsize=14, pad=20)  # 设置标题,字体大小14,下边距20
plt.xlabel('股票', fontsize=12)  # 设置x轴标签
plt.ylabel('股票', fontsize=12)  # 设置y轴标签
plt.tight_layout()  # 自动调整子图参数,使图形紧凑美观
plt.show()  # 显示图形

代码深度解析:

  1. 配色方案选择:
    • coolwarm: 蓝红渐变,适合温度数据
    • RdYlGn: 红黄绿渐变,金融常用
    • RdBu: 红蓝渐变,色盲友好
    • viridis: 感知均匀,适合黑白打印
  2. 参数说明:
    • center=0: 强调正负相关对比
    • square=True: 保持格子为正方形
    • annot=True: 显示数值便于精确解读
    • fmt: 数值格式,.3f保留三位小数
  3. 可读性优化:
    • 使用清晰的中文字体
    • 合理的图形尺寸
    • 清晰的标题和标签

21.4.2 高级热力图

列表 21.6
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 绘制带层次聚类的相关性热力图
# =============================================================================
# 本代码块演示如何在热力图基础上添加层次聚类,将相似的股票聚集在一起。
# 层次聚类可以揭示数据中自然的分组结构,在金融中常用于识别行业板块、
# 风格因子等。聚类后的热力图更容易发现股票之间的共同特征。

# ==================== 导入层次聚类库 ====================
from scipy.cluster.hierarchy import linkage, dendrogram  # 导入层次聚类相关函数
from scipy.spatial.distance import squareform  # 导入距离矩阵转换函数

# ==================== 层次聚类链接 ====================
# linkage()函数执行层次聚类,返回链接矩阵
# method='average'表示使用平均链接法(UPGMA)
# 相关性转换为距离: distance = 1 - abs(correlation)
linkage_matrix = linkage(corr_matrix, method='average')  # 计算层次聚类的链接矩阵

# ==================== 绘制带聚类的热力图 ====================
g = sns.clustermap(
    corr_matrix,  # 输入相关系数矩阵
    annot=True,  # 显示数值注释
    cmap='RdYlGn',  # 颜色方案
    center=0,  # 颜色中心值
    square=True,  # 正方形格子
    linewidths=0.5,  # 边框线宽
    fmt='.3f',  # 数值格式
    figsize=(10, 10),  # 图形尺寸
    row_linkage=linkage_matrix,  # 行聚类链接矩阵
    col_linkage=linkage_matrix,  # 列聚类链接矩阵
    cbar_pos=(0.02, 0.8, 0.05, 0.18),  # 颜色条位置(左,下,宽,高)
    tree_kws={'linewidths': 1.5}  # 树状图线宽
)

# ==================== 设置标题 ====================
g.fig.suptitle('股票相关性聚类分析', fontsize=14, y=0.98)  # 设置图形总标题
plt.show()  # 显示图形

# ==================== 分析聚类结果 ====================
print('聚类树分析:')  # 打印标题
print('相近股票被分在同一类,表明受共同因子影响')  # 打印解释

补充说明:层次聚类方法

层次聚类通过距离度量将相似股票分组:

距离定义: - 基于相关性: \(distance = 1 - |\rho|\) - 单链接: 最小距离 - 完全链接: 最大距离 - 平均链接: 平均距离(本例使用)

金融应用: 1. 行业识别: 同行业股票聚在一起 2. 风格因子: 价值vs成长 3. 地域因子: 同地区股票相关 4. 风险因子: 暴露于共同风险

21.4.3 网络图可视化

列表 21.7
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 绘制股票相关性网络图
# =============================================================================
# 本代码块演示如何使用网络图(Network Graph)可视化股票之间的相关性。
# 网络图将股票表示为节点,相关性表示为边,可以直观展示股票之间的
# 关联结构和系统重要性。网络分析在系统性风险研究中具有重要应用。

# ==================== 导入网络图库 ====================
import networkx as nx  # 导入networkx库,用于网络分析

# ==================== 创建网络图(只保留强相关性) ====================
threshold = 0.5  # 设置相关系数阈值为0.5,只保留强相关性
G = nx.Graph()  # 创建无向图对象

# ==================== 添加节点 ====================
for stock in stocks.values():  # 遍历所有股票名称
    G.add_node(stock)  # 为每只股票添加一个节点

# ==================== 添加边(只保留强相关) ====================
for i in range(n):  # 遍历股票i
    for j in range(i+1, n):  # 遍历股票j(j>i,避免重复)
        stock1 = corr_matrix.index[i]  # 获取股票i的名称
        stock2 = corr_matrix.columns[j]  # 获取股票j的名称
        corr = corr_matrix.iloc[i, j]  # 获取这对股票的相关系数
        if abs(corr) >= threshold:  # 判断相关系数绝对值是否超过阈值
            G.add_edge(stock1, stock2, weight=corr)  # 添加边,边的权重为相关系数

# ==================== 绘制网络图 ====================
plt.figure(figsize=(10, 8))  # 创建图形
pos = nx.spring_layout(G, k=0.5, seed=42)  # 使用弹簧布局算法计算节点位置
# k参数控制节点间的距离,k越大节点越分散
# seed参数确保布局可复现

# ==================== 绘制节点 ====================
# 节点颜色映射度(连接数),度数越大的节点越大
degrees = dict(G.degree())  # 获取每个节点的度数(连接数)
nx.draw_networkx_nodes(
    G, pos,  # 图对象和位置字典
    node_size=[v * 300 for v in degrees.values()],  # 节点大小与度数成正比
    node_color='steelblue',  # 节点颜色为钢蓝色
    alpha=0.7  # 透明度0.7
)

# ==================== 绘制边 ====================
# 边的颜色和粗细映射相关性
edges = G.edges()  # 获取所有边
weights = [G[u][v]['weight'] for u, v in edges]  # 提取每条边的权重(相关系数)
edge_colors = ['red' if w < 0 else 'green' for w in weights]  # 负相关用红色,正相关用绿色
nx.draw_networkx_edges(
    G, pos,  # 图对象和位置字典
    width=[abs(w) * 3 for w in weights],  # 边的宽度与相关系数绝对值成正比
    edge_color=edge_colors,  # 边的颜色
    alpha=0.6  # 透明度0.6
)

# ==================== 绘制节点标签 ====================
nx.draw_networkx_labels(G, pos, font_size=10, font_family='sans-serif')  # 绘制节点标签(股票名称)

# ==================== 设置图形属性 ====================
plt.title(f'股票相关性网络图(阈值={threshold})', fontsize=14)  # 设置标题
plt.axis('off')  # 关闭坐标轴
plt.tight_layout()  # 调整布局
plt.show()  # 显示图形

# ==================== 网络分析统计 ====================
print('网络分析:')  # 打印标题
print(f'节点数(股票数): {G.number_of_nodes()}')  # 打印节点数量
print(f'边数(强相关对): {G.number_of_edges()}')  # 打印边数量(强相关股票对数量)
print(f'平均度数: {sum(dict(G.degree()).values()) / G.number_of_nodes():.2f}')  # 打印平均度数

补充说明:网络图解读

网络图将股票表示为节点,相关性表示为边:

  1. 节点大小: 度数(连接数),代表与其他股票的相关程度
  2. 边的颜色: 红色=负相关,绿色=正相关
  3. 边的粗细: 相关系数绝对值,越粗相关越强
  4. 节点位置: 相近节点更相关

金融应用: - 中心节点: 系统重要性高,对市场影响大 - 孤立节点: 独立走势,适合分散化 - 紧密聚类: 行业或风格因子

21.5 相关性的动态变化

21.5.1 滚动窗口相关性

列表 21.8
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# =============================================================================
# 题目: 计算和可视化滚动窗口相关性
# =============================================================================
# 本代码块演示如何计算滚动窗口相关性并可视化其动态变化。滚动相关性可以
# 揭示股票关系的时变特征,这对于理解市场状态转换、危机传染和投资组合
# 动态调整非常重要。相关性的不稳定性是现代金融理论的核心发现之一。

# ==================== 选择两只高相关股票 ====================
stock_a = '中信证券'  # 第一只股票
stock_b = '中国平安'  # 第二只股票

# ==================== 计算滚动相关性(20日窗口) ====================
window = 20  # 设置滚动窗口大小为20个交易日(约1个月)
# rolling(window).corr()计算滚动窗口相关系数
# 对两个Series计算corr()返回滚动相关系数序列
rolling_corr = log_returns[stock_a].rolling(window).corr(log_returns[stock_b])

# ==================== 绘制滚动相关性 ====================
fig, axes = plt.subplots(2, 1, figsize=(14, 10))  # 创建2行1列的子图

# ==================== 子图1:滚动相关性 ====================
axes[0].plot(rolling_corr.index, rolling_corr, linewidth=2)  # 绘制滚动相关系数曲线
axes[0].axhline(y=0, color='k', linestyle='--', linewidth=1)  # 添加0参考线(黑色虚线)
axes[0].axhline(y=0.5, color='r', linestyle='--', linewidth=1, label='阈值0.5')  # 添加0.5阈值线(红色虚线)
axes[0].axhline(y=-0.5, color='r', linestyle='--', linewidth=1, label='阈值-0.5')  # 添加-0.5阈值线
axes[0].set_title(f'{stock_a}{stock_b}的滚动相关性(窗口={window}日)', fontsize=12)  # 设置标题
axes[0].set_ylabel('相关系数', fontsize=10)  # 设置y轴标签
axes[0].legend(fontsize=10)  # 显示图例
axes[0].grid(True, alpha=0.3)  # 显示网格,透明度0.3

# ==================== 子图2:价格走势(归一化) ====================
# 归一化价格:将初始价格设为100,便于比较不同价格水平的股票
# 公式: 归一化价格 = (原价格 / 初始价格) × 100
norm_prices = df_prices[[stock_a, stock_b]] / df_prices[[stock_a, stock_b]].iloc[0] * 100
axes[1].plot(norm_prices.index, norm_prices[stock_a], label=stock_a, linewidth=2)  # 绘制股票A的归一化价格
axes[1].plot(norm_prices.index, norm_prices[stock_b], label=stock_b, linewidth=2)  # 绘制股票B的归一化价格
axes[1].set_title('归一化价格走势', fontsize=12)  # 设置标题
axes[1].set_ylabel('初始价格=100', fontsize=10)  # 设置y轴标签
axes[1].legend(fontsize=10)  # 显示图例
axes[1].grid(True, alpha=0.3)  # 显示网格

plt.tight_layout()  # 调整布局
plt.show()  # 显示图形

# ==================== 滚动相关性统计 ====================
print('滚动相关性分析:')  # 打印标题
print(f'平均相关性: {rolling_corr.mean():.3f}')  # 打印滚动相关系数的均值
print(f'相关性标准差: {rolling_corr.std():.3f}')  # 打印滚动相关系数的标准差
print(f'相关性范围: [{rolling_corr.min():.3f}, {rolling_corr.max():.3f}]')  # 打印最小值和最大值

金融应用:相关性的不稳定性

相关系数不是恒定的,它会随时间变化:

  1. 市场状态依赖:
    • 牛市:股票普遍同涨,相关性高
    • 熊市:恐慌抛售,相关性极高(相关性崩塌)
    • 震荡市:个股分化,相关性降低
  2. 危机期间:
    • 2008金融危机:所有资产相关性趋近1
    • 分散化失效
    • 对冲困难
  3. 策略启示:
    • 不能依赖历史相关性
    • 需要动态监控相关性
    • 极端事件时相关性可能逆转